package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/widget"
	"github.com/pdfcpu/pdfcpu/pkg/api"
	"github.com/signintech/gopdf"
	"github.com/unidoc/unipdf/v3/model"
)

func main() {
	a := app.New()
	w := a.NewWindow("PDF split & merge")
	w.Resize(fyne.NewSize(800, 600))

	tabs := container.NewAppTabs(
		container.NewTabItem("Split PDF", createSplitTab(w)),
		container.NewTabItem("Merged PDF", createMergeTab(w)),
	)

	w.SetContent(tabs)
	w.ShowAndRun()
}

func createSplitTab(window fyne.Window) fyne.CanvasObject {
	fileEntry := widget.NewEntry()
	fileEntry.Disable()

	fileSelectBtn := widget.NewButton("Select file", func() {
		dialog.ShowFileOpen(func(reader fyne.URIReadCloser, err error) {
			if err != nil {
				dialog.ShowError(err, window)
				return
			}
			if reader == nil {
				return
			}

			fileEntry.SetText(reader.URI().Path())
		}, window)
	})

	allSplitCheckbox := widget.NewCheck("All split", func(checked bool) {
		// Do something based on checkbox state
	})

	splitBtn := widget.NewButton("split", func() {
		filePath := fileEntry.Text
		if filePath == "" {
			dialog.ShowError(fmt.Errorf("Please select a PDF file"), window)
			return
		}

		file, err := os.Open(filePath)
		if err != nil {
			dialog.ShowError(err, window)
			return
		}
		defer file.Close()

		pdfReader, err := model.NewPdfReader(file)
		if err != nil {
			dialog.ShowError(err, window)
			return
		}

		numPages, err := pdfReader.GetNumPages()
		if err != nil {
			dialog.ShowError(err, window)
			return
		}

		splitAll := allSplitCheckbox.Checked
		startPage := 1
		endPage := numPages

		if !splitAll {
			startPageEntry := widget.NewEntry()
			endPageEntry := widget.NewEntry()

			layout := container.NewVBox(
				widget.NewLabel("The start page:"),
				startPageEntry,
				widget.NewLabel("trailer page:"),
				endPageEntry,
			)

			dialog.ShowCustom("Select pages\n", "cancel", layout, window)

			layout.Add(widget.NewButton("confirm", func() {
				start, err := strconv.Atoi(startPageEntry.Text)
				if err != nil {
					dialog.ShowError(fmt.Errorf("Invalid start pages"), window)
					return
				}

				end, err := strconv.Atoi(endPageEntry.Text)
				if err != nil {
					dialog.ShowError(fmt.Errorf("Invalid the end of the page"), window)
					return
				}

				startPage = start
				endPage = end
				splitPDF(filePath, startPage, endPage, window)
			}))
		} else {
			splitPDF(filePath, startPage, endPage, window)
		}
	})

	return container.NewVBox(
		widget.NewLabel("Choose to split PDF files:"),
		container.NewVBox(fileEntry, fileSelectBtn),
		allSplitCheckbox,
		splitBtn,
	)
}

func splitPDF(filePath string, startPage int, endPage int, window fyne.Window) {
	file, err := os.Open(filePath)
	if err != nil {
		dialog.ShowError(err, window)
		return
	}
	defer file.Close()

	basePath := "./split_output"
	err = os.MkdirAll(basePath, os.ModePerm)
	if err != nil {
		dialog.ShowError(err, window)
		return
	}

	for pageNum := startPage; pageNum <= endPage; pageNum++ {
		if err := api.ExtractPagesFile(filePath, basePath, []string{strconv.Itoa(pageNum)}, nil); err != nil {
			dialog.ShowError(err, window)
			return
		}

	}

	dialog.ShowInformation("succeed", "A PDF file has been successfully break up", window)
}

func createMergeTab(window fyne.Window) fyne.CanvasObject {
	filesEntry := widget.NewMultiLineEntry()
	filesEntry.SetPlaceHolder("Will be merged PDF file path ")

	mergeBtn := widget.NewButton("merge", func() {
		filePaths := splitLines(filesEntry.Text)
		if len(filePaths) == 0 {
			dialog.ShowError(fmt.Errorf("Please provide the path of the PDF files to be combined"), window)
			return
		}

		mergedPath := "./merged_output/mege.pdf"
		err := mergePDFs(filePaths, mergedPath)
		if err != nil {
			dialog.ShowError(err, window)
			return
		}

		dialog.ShowInformation("succeed", "PDF file has been successfully merged", window)
	})

	return container.NewVBox(
		widget.NewLabel("Choose to merge the PDF files:"),
		filesEntry,
		mergeBtn,
	)
}

func mergePDFs(filePaths []string, mergedPath string) error {
	var err error
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})

	// 得到每个文件的路径后,将每个pdf文件读取出来,最后合并成一个pdf文件
	// 创建输出文件
	output, err := os.Create(mergedPath)
	if err != nil {
		fmt.Println("Unable to create the output file:", err)
		return err
	}
	defer output.Close()

	// 定义合并选项
	// 合并PDF文件
	err = api.MergeCreateFile(filePaths, mergedPath, nil)
	if err != nil {
		fmt.Println("An error occurred when merging PDF files:", err)
		return err
	}

	return nil

}

func splitLines(text string) []string {
	lines := []string{}
	for _, line := range strings.Split(text, "\n") {
		line = strings.TrimSpace(line)
		if line != "" {
			lines = append(lines, line)
		}
	}
	return lines
}
